import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
import java.util.Random;

public class SnakeGame extends JFrame {

    // 游戏中每个方块的大小
    private static final int TILE_SIZE = 25;
    // 游戏窗口的宽度
    private static final int WIDTH = 800;
    // 游戏窗口的高度
    private static final int HEIGHT = 600;
    // 游戏中总方块数
    private static final int ALL_TILES = (WIDTH * HEIGHT) / (TILE_SIZE * TILE_SIZE);

    // 蛇的身体，使用LinkedList存储
    private LinkedList<Point> snake;
    // 食物的位置
    private Point food;
    // 蛇的移动方向，初始为向右
    private char direction = 'R'; // U, D, L, R
    // 游戏是否正在运行
    private boolean running = false;
    // 游戏面板
    private GamePanel panel;
    // 游戏线程
    private Thread gameThread;
    // 游戏得分
    private int score = 0;
    // 用于控制蛇身体颜色闪烁的标志位
    private boolean flash = false;
    // 背景图片
    private Image backgroundImage;
    // 食物图片
    private Image foodImage;

    // 构造函数，初始化游戏窗口
    public SnakeGame() {
        setTitle("多线程贪吃蛇游戏");
        setSize(WIDTH, HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);

        // 加载背景图片
        ImageIcon backgroundIcon = new ImageIcon("background.jpg");
        backgroundImage = backgroundIcon.getImage();

        // 加载食物图片
        ImageIcon foodIcon = new ImageIcon("images/food.png");
        foodImage = foodIcon.getImage();

        // 添加游戏面板
        panel = new GamePanel();
        add(panel);
        // 添加键盘监听器
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_UP:
                        if (direction != 'D') direction = 'U';
                        break;
                    case KeyEvent.VK_DOWN:
                        if (direction != 'U') direction = 'D';
                        break;
                    case KeyEvent.VK_LEFT:
                        if (direction != 'R') direction = 'L';
                        break;
                    case KeyEvent.VK_RIGHT:
                        if (direction != 'L') direction = 'R';
                        break;
                    case KeyEvent.VK_SPACE:
                        if (!running) startGame();
                        break;
                }
            }
        });

        // 初始化游戏
        initGame();
    }

    // 初始化游戏状态
    private void initGame() {
        snake = new LinkedList<>();
        snake.add(new Point(5, 5));
        snake.add(new Point(4, 5));
        snake.add(new Point(3, 5));
        spawnFood();
        score = 0;
        direction = 'R';
    }

    // 随机生成食物位置
    private void spawnFood() {
        Random rand = new Random();
        int x, y;
        do {
            x = rand.nextInt(WIDTH / TILE_SIZE);
            y = rand.nextInt(HEIGHT / TILE_SIZE);
            food = new Point(x, y);
        } while (snake.contains(food));
    }

    // 开始游戏
    private void startGame() {
        if (gameThread != null && gameThread.isAlive()) {
            gameThread.interrupt();
        }

        initGame();
        running = true;

        // 创建并启动游戏线程
        gameThread = new Thread(() -> {
            while (running) {
                try {
                    // 控制游戏速度，分数越高，速度越快
                    Thread.sleep(150 - Math.min(score / 10, 100));
                    // 切换颜色闪烁标志位
                    flash =!flash;
                    move(); // 移动蛇
                    checkCollision(); // 检查碰撞
                    panel.repaint(); // 重绘游戏面板
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }

            if (!running) {
                // 游戏结束后显示得分对话框
                SwingUtilities.invokeLater(() -> {
                    JOptionPane.showMessageDialog(this, "游戏结束! 得分: " + score,
                            "游戏结束", JOptionPane.INFORMATION_MESSAGE);
                });
            }
        });

        gameThread.start(); // 启动游戏线程
    }

    // 移动蛇
    private void move() {
        Point head = snake.getFirst();
        Point newHead = switch (direction) {
            case 'U' -> new Point(head.x, head.y - 1);
            case 'D' -> new Point(head.x, head.y + 1);
            case 'L' -> new Point(head.x - 1, head.y);
            case 'R' -> new Point(head.x + 1, head.y);
            default -> new Point(head.x, head.y);
        };

        snake.addFirst(newHead);
        if (newHead.equals(food)) {
            score += 10;
            spawnFood();
        } else {
            snake.removeLast();
        }
    }

    // 检查碰撞
    private void checkCollision() {
        Point head = snake.getFirst();

        // 检查是否撞墙
        if (head.x < 0 || head.x >= WIDTH / TILE_SIZE ||
                head.y < 0 || head.y >= HEIGHT / TILE_SIZE) {
            running = false;
        }

        // 检查是否撞到自己
        for (int i = 1; i < snake.size(); i++) {
            if (head.equals(snake.get(i))) {
                running = false;
                break;
            }
        }
    }

    // 游戏面板类
    private class GamePanel extends JPanel {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // 绘制背景图片
            g.drawImage(backgroundImage, 0, 0, null);

            // 绘制蛇
            Color snakeColor = flash? Color.YELLOW : Color.GREEN;
            g.setColor(snakeColor);
            for (Point p : snake) {
                g.fillRect(p.x * TILE_SIZE, p.y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
            }

            // 绘制蛇头
            if (!snake.isEmpty()) {
                g.setColor(new Color(0, 150, 0));
                Point head = snake.getFirst();
                g.fillRect(head.x * TILE_SIZE, head.y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
            }

            // 绘制食物图片
            g.drawImage(foodImage, food.x * TILE_SIZE, food.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, null);

            // 绘制分数
            g.setColor(Color.BLACK);
            g.setFont(new Font("Arial", Font.BOLD, 20));
            g.drawString("score: " + score, 10, 20);

            // 如果游戏未开始，显示开始提示
            if (!running) {
                g.setColor(Color.WHITE);
                g.setFont(new Font("Arial", Font.BOLD, 30));
                String msg = snake.size() > 3? "游戏结束! 按空格键重新开始" : "按空格键开始游戏";
                g.drawString(msg, (WIDTH - g.getFontMetrics().stringWidth(msg)) / 2, HEIGHT / 2);
            }
        }
    }

    // 主函数，启动游戏
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            SnakeGame game = new SnakeGame();
            game.setVisible(true);
        });
    }
}